package com.xjh.basestudy.designmode.behaviorMode.behaviorMode9_Visitor.p2_batch;

import com.xjh.basestudy.designmode.behaviorMode.behaviorMode9_Visitor.p2_batch.DiscountVisitor;
import com.xjh.basestudy.designmode.behaviorMode.behaviorMode9_Visitor.p2_batch.Visitor;

import java.time.LocalDate;
import java.util.Arrays;
import java.util.List;

/**
 * @Author XuJianHua
 * @Date 2022/10/5 21:38
 * @Description 客户端代码改动并不大，第5行的购物车只是将之前的商品类泛型<Product>换成了接待者泛型<Acceptable>，
 * 也就是说，所有商品都能够作为“接待者”接受排查了（类似于为每件商品贴上条码）。同样，在第13行的购物车商品迭代中，我们也以Acceptable来承接每件商品，
 * 并在第14行让这些商品对象主动地去“接待”访问者（discountVisitor），这样一来编译错误就消失了，第17行的输出结果显示一切正常，
 * 糖果对象被成功“派发”到了重载方法visit(Candy candy)中。简单来讲，因为重载方法不允许将泛型对象作为入参，所以我们先让接待者将访问者“派发”到自己的接待方法中，
 * 要访问先接待，然后再将自己（此时this已经是确切的对象类型了）“派发”回给访问者，告知自己的身份。这时访问者也明确知道应该调用哪个重载方法了，
 * 2次派发成功地化解了重载方法与泛型间的矛盾。至此，超市再也不必为复杂多变的计价方式或者业务逻辑而发愁了，
 * 只需要像填表格一样为每类商品添加计价方法就可以了。例如超市为迎接六一儿童节举办打折活动，我们便可以添加新的访问者类，增加对糖果类、玩具类的打折力度，接入系统
 */
public class Client {

    public static void main(String[] args) {
        // 3件商品加入购物车
        List<Acceptable> products = Arrays.asList(
                new Candy("小兔奶糖", LocalDate.of(2018, 10, 1), 20.00f),
                new Wine("老猫白酒", LocalDate.of(2017, 1, 1), 1000.00f),
                new Fruit("草莓", LocalDate.of(2018, 12, 26), 10.00f, 2.5f)
        );

        Visitor discountVisitor = new DiscountVisitor(LocalDate.of(2019, 1, 1));
        // 迭代购物车中的商品
        for (Acceptable product : products) {
            product.accept(discountVisitor);
        }

       /*输出：
          结算日期：2019-01-01
          =====糖果【小兔奶糖】打折后价格=====
          ￥18.00
          =====酒品【老猫白酒】无折扣价格=====
          ￥1,000.00
          =====水果【草莓】打折后价格=====
          ￥12.50
        */
    }
}